home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 1997 #3 / Amiga Plus CD - 1997 - No. 03.iso / pd / programmierung / vbcc / ic.c < prev    next >
C/C++ Source or Header  |  1997-01-31  |  49KB  |  1,363 lines

  1. /*  $VER: vbcc (ic.c) V0.4  */
  2.  
  3. #include "vbc.h"
  4.  
  5. static char FILE_[]=__FILE__;
  6.  
  7. struct IC *first_ic=0,*last_ic=0;
  8. int float_used;
  9.  
  10. int do_arith(np,struct IC *,np,struct obj *);
  11.  
  12. void gen_test(struct obj *o,int t,int branch,int label)
  13. /*  Generiert ein test o, branch label und passt auf, dass      */
  14. /*  kein TEST const generiert wird.                             */
  15. {
  16.     struct IC *new;
  17.     if(o->flags&KONST){
  18.         eval_const(&o->val,t);
  19.         if(zdeqto(vdouble,d2zd(0.0))&&zleqto(vlong,l2zl(0L))&&zuleqto(vulong,ul2zul(0UL))){
  20.             if(branch==BEQ) branch=BRA; else branch=0;
  21.         }else{
  22.             if(branch==BNE) branch=BRA; else branch=0;
  23.         }
  24.     }else{
  25.         new=mymalloc(ICS);
  26.         new->code=TEST;
  27.         new->q2.flags=new->z.flags=0;
  28.         new->typf=t;
  29.         new->q1=*o;
  30.         add_IC(new);
  31.     }
  32.     if(branch){
  33.         new=mymalloc(ICS);
  34.         new->code=branch;
  35.         new->typf=label;
  36.         add_IC(new);
  37.     }
  38. }
  39.  
  40. void inline_memcpy(np z,np q,zlong size)
  41. /*  fuegt ein ASSIGN-IC ein, das memcpy(z,q,size) entspricht    */
  42. {
  43.     struct IC *new=mymalloc(ICS);
  44.     if((z->ntyp->flags&15)!=POINTER) ierror(0);
  45.     if((q->ntyp->flags&15)!=POINTER) ierror(0);
  46.  
  47.     gen_IC(z,0,0);
  48.     if(z->o.flags&DREFOBJ){
  49.         struct IC *n2=mymalloc(ICS);
  50.         n2->code=ASSIGN;
  51.         n2->typf=q->ntyp->flags;
  52.         n2->q1=z->o;
  53.         get_scratch(&n2->z,z->ntyp->flags,z->ntyp->next->flags);
  54.         n2->q2.flags=0;
  55.         n2->q2.val.vlong=sizetab[POINTER];
  56.         new->z=n2->z;
  57.         add_IC(n2);
  58.     }else{
  59.         new->z=z->o;
  60.     }
  61.     if(new->z.flags&VARADR) new->z.flags&=~VARADR; else new->z.flags|=DREFOBJ;
  62.  
  63.     gen_IC(q,0,0);
  64.     if(q->o.flags&DREFOBJ){
  65.         struct IC *n2=mymalloc(ICS);
  66.         n2->code=ASSIGN;
  67.         n2->typf=q->ntyp->flags;
  68.         n2->q1=q->o;
  69.         get_scratch(&n2->z,q->ntyp->flags,q->ntyp->next->flags);
  70.         n2->q2.flags=0;
  71.         n2->q2.val.vlong=sizetab[POINTER];
  72.         new->q1=n2->z;
  73.         add_IC(n2);
  74.     }else{
  75.         new->q1=q->o;
  76.     }
  77.     if(new->q1.flags&VARADR) new->q1.flags&=~VARADR; else new->q1.flags|=DREFOBJ;
  78.  
  79.     new->code=ASSIGN;
  80.     new->typf=UNSIGNED|CHAR;
  81.     new->q2.flags=0;
  82.     new->q2.val.vlong=size;
  83.     add_IC(new);
  84. }
  85.  
  86. void add_IC(struct IC *new)
  87. /*  fuegt ein IC ein                                            */
  88. {
  89.     int code;
  90.     if(!new) return;
  91.     if(nocode) {free(new);return;}
  92.     new->next=0;
  93.     new->q1.am=new->q2.am=new->z.am=0;
  94.     new->line=line; new->file=0;
  95.     code=new->code;
  96.     if(code>=BEQ&&code<=BRA) new->q1.flags=new->q2.flags=new->z.flags=0;
  97.     if(code==ALLOCREG||code==FREEREG||code==SAVEREGS||code==RESTOREREGS) new->typf=0;
  98.     if(DEBUG&64) pric2(stdout,new);
  99.     if(new->q1.flags&VAR){
  100.         if(!new->q1.v) ierror(0);
  101.         new->q1.v->flags|=USEDASSOURCE;
  102.         if(code==ADDRESS||(new->q1.flags&VARADR)) new->q1.v->flags|=USEDASADR;
  103.         new->q1.v->priority+=currentpri;
  104.     }
  105.     if(new->q2.flags&VAR){
  106.         if(!new->q2.v) ierror(0);
  107.         new->q2.v->flags|=USEDASSOURCE;
  108.         if(code==ADDRESS||(new->q2.flags&VARADR)) new->q2.v->flags|=USEDASADR;
  109.         new->q2.v->priority+=currentpri;
  110.     }
  111.     if(new->z.flags&VAR){
  112.         if(!new->z.v) ierror(0);
  113.         if(new->z.flags&DREFOBJ) new->z.v->flags|=USEDASSOURCE; else new->z.v->flags|=USEDASDEST;
  114.         new->z.v->priority+=currentpri;
  115.     }
  116.     if(/*(c_flags_val[0].l&2)&&*/code==LABEL){
  117.     /*  entfernt Spruenge zu direkt folgenden Labels    */
  118.         struct IC *p=last_ic;
  119.         while(p){
  120.             if(p->typf==new->typf&&p->code>=BEQ&&p->code<=BRA){
  121.                 struct IC *n;
  122.                 if(DEBUG&1) printf("%s l%d deleted\n",ename[p->code],p->typf);
  123.                 n=p->next;
  124.                 remove_IC(p);
  125.                 p=n;
  126.             }else{
  127.                 if(p->code!=LABEL) break;
  128.                 p=p->prev;
  129.             }
  130.         }
  131.     }
  132.     if(last_ic){
  133.         if(code==ASSIGN){
  134.             if((last_ic->z.flags&(REG|SCRATCH|DREFOBJ))==(REG|SCRATCH)&&(new->q1.flags==last_ic->z.flags)&&last_ic->z.reg==new->q1.reg/*&&last_ic->code!=CALL*/){
  135.                 if(USEQ2ASZ||!(last_ic->q2.flags®)||!(new->z.flags®)||last_ic->q2.reg!=new->z.reg){
  136.                     if(USEQ2ASZ||!(last_ic->q2.flags&VAR)||!(new->z.flags&VAR)||last_ic->q2.v!=new->z.v){
  137.                     /*  verbindet op a,b->reg,move reg->c zu op a,b->c  */
  138.                     /*  hier fehlt aber noch Registerfreigabe           */
  139.                         last_ic->z=new->z;
  140.                         if(DEBUG&1) printf("move and op combined\n");
  141.                         if((new->q1.flags&SCRATCH)&&(new->q1.reg!=new->z.reg||!(new->z.flags®)))
  142.                             free_reg(new->q1.reg);
  143.                         free(new);
  144.                         return;
  145.                     }
  146.                 }
  147.             }
  148.             if((last_ic->z.flags&(VAR|SCRATCH|DREFOBJ))==(VAR|SCRATCH)&&(new->q1.flags==last_ic->z.flags)&&last_ic->z.v==new->q1.v/*&&last_ic->code!=CALL*/){
  149.                 if(USEQ2ASZ||!(last_ic->q2.flags®)||!(new->z.flags®)||last_ic->q2.reg!=new->z.reg){
  150.                     if(USEQ2ASZ||!(last_ic->q2.flags&VAR)||!(new->z.flags&VAR)||last_ic->q2.v!=new->z.v){
  151.                     /*  verbindet op a,b->scratch,move scratch->c zu op a,b->c  */
  152.                     /*  hier fehlt aber noch Registerfreigabe           */
  153.                         last_ic->z=new->z;
  154.                         if(DEBUG&1) printf("move and op combined(2)\n");
  155. /*                        if((new->q1.flags&SCRATCH)&&(new->q1.reg!=new->z.reg||!(new->z.flags®)))
  156.                             free_reg(new->q1.reg);*/
  157.                         free(new);
  158.                         return;
  159.                     }
  160.                 }
  161.             }
  162.  
  163.         }
  164.         if(last_ic->code==BRA){
  165.             if(code!=LABEL&&code!=ALLOCREG&&code!=FREEREG){
  166.             /*  loescht alles nach bra bis ein Label kommt  */
  167.             /*  momentan noch nicht perfekt, da es bei alloc/freereg stoppt */
  168.                 free(new);
  169.                 if(DEBUG&1) printf("Unreachable Statement deleted\n");
  170.                 return;
  171.             }
  172.             if(last_ic->prev&&code==LABEL){
  173.             /*  ersetzt bcc l1;bra l2;l1 durch b!cc l2      */
  174.                 if(last_ic->prev->code>=BEQ&&last_ic->prev->code<=BGT&&new->typf==last_ic->prev->typf){
  175.                     if(DEBUG&1) printf("%s l%d;%s l%d; substituted\n",ename[last_ic->prev->code],last_ic->prev->typf,ename[last_ic->code],last_ic->typf);
  176.                     if(last_ic->prev->code&1) last_ic->prev->code--;
  177.                                     else      last_ic->prev->code++;
  178.                     last_ic->prev->typf=last_ic->typf;
  179.                     last_ic=last_ic->prev;
  180.                     free(last_ic->next);
  181.                     last_ic->next=new;new->prev=last_ic;
  182.                     last_ic=new;
  183.                     return;
  184.                 }
  185.             }
  186.         }
  187. /*        }*/
  188.         new->prev=last_ic;
  189.         last_ic->next=new;
  190.         last_ic=new;
  191.     }else{
  192.         last_ic=new;first_ic=new;new->prev=0;
  193.     }
  194.     ic_count++;
  195.     /*  Merken, on Fliesskomma benutzt wurde    */
  196.     if(code!=LABEL&&(code<BEQ||code>BRA))
  197.         if((new->typf&15)==FLOAT||(new->typf&15)==DOUBLE) float_used=1;
  198.     if((new->q1.flags&SCRATCH)&&(new->q1.reg!=new->z.reg||!(new->z.flags®)))
  199.         free_reg(new->q1.reg);
  200.     if((new->q2.flags&SCRATCH)&&(new->q2.reg!=new->z.reg||!(new->z.flags®)))
  201.         free_reg(new->q2.reg);
  202. }
  203. void free_IC(struct IC *p)
  204. /*  Gibt IC-Liste inkl. Typen frei                  */
  205. {
  206.     struct IC *merk;
  207.     if(DEBUG&1) printf("free_IC()\n");
  208.     while(p){
  209.         if(p->q1.am) free(p->q1.am);
  210.         if(p->q2.am) free(p->q2.am);
  211.         if(p->z.am) free(p->z.am);
  212.         merk=p->next;
  213.         free(p);
  214.         p=merk;
  215.     }
  216. }
  217. void gen_IC(np p,int ltrue,int lfalse)
  218. /*  Erzeugt eine IC-Liste aus einer expression      */
  219. {
  220.     struct IC *new; struct regargs_list *rl;
  221.     if(!p) return;
  222.     if(p->flags==STRING){
  223.     /*  hier fehlt noch die Verwaltung der String-Inhalte   */
  224.         p->o.v=add_var(empty,clone_typ(p->ntyp),STATIC,(struct const_list *)p->identifier);
  225.         p->o.v->flags|=DEFINED;
  226.         p->o.flags=VAR;
  227.         p->o.reg=0;
  228.         p->o.val=p->val;
  229.         return;
  230.     }
  231.     if(p->flags==IDENTIFIER){
  232. /*        p->o.v=find_var(p->identifier,0);*/
  233.         p->o.flags=VAR;
  234.         p->o.reg=0;
  235.         p->o.val=p->val;
  236.         return;
  237.     }
  238.     if(p->flags==CEXPR||p->flags==PCEXPR){
  239.         if(p->left){
  240.             if(p->left->flags==POSTINC) p->left->flags=PREINC;
  241.             if(p->left->flags==POSTDEC) p->left->flags=PREDEC;
  242.             gen_IC(p->left,0,0);
  243.             if(p->left->o.flags&SCRATCH) free_reg(p->left->o.reg);
  244.         }
  245.         if(p->right){
  246.             if(p->right->flags==POSTINC) p->right->flags=PREINC;
  247.             if(p->right->flags==POSTDEC) p->right->flags=PREDEC;
  248.             gen_IC(p->right,0,0);
  249.             if(p->right->o.flags&SCRATCH) free_reg(p->right->o.reg);
  250.         }
  251.         p->o.flags=KONST;
  252.         p->o.val=p->val;
  253.         p->o.reg=0;
  254.         return;
  255.     }
  256.     if(p->flags==KOMMA){
  257.         if(p->left->sidefx){
  258.             gen_IC(p->left,0,0);
  259.             if(p->left->o.flags&SCRATCH) free_reg(p->left->o.reg);
  260.         } else error(129);
  261.         gen_IC(p->right,0,0);
  262.         p->o=p->right->o;
  263.         return;
  264.     }
  265.     if(p->flags==CAST){
  266.         gen_IC(p->left,0,0);
  267.         convert(p->left,p->ntyp->flags&31);
  268.         p->o=p->left->o;
  269.         return;
  270.     }
  271.     if(p->flags==FIRSTELEMENT){
  272.         gen_IC(p->left,0,0);
  273.         p->o=p->left->o;
  274.         return;
  275.     }
  276.     new=mymalloc(ICS);
  277.     new->typf=p->ntyp->flags&31;
  278.     new->q1.reg=new->q2.reg=new->z.reg=0;
  279.     new->q1.flags=new->q2.flags=new->z.flags=0;
  280.     if((p->flags>=LSHIFT&&p->flags<=MOD)||(p->flags>=OR&&p->flags<=AND)||p->flags==PMULT){
  281.         do_arith(p,new,0,0);
  282.         return;
  283.     }
  284.     if(p->flags==CONTENT){
  285.         gen_IC(p->left,0,0);
  286.         if(p->left->o.flags&VARADR){
  287.             free(new);
  288.             p->o=p->left->o;
  289.             p->o.flags&=~VARADR;
  290.             return;
  291.         }
  292.         if(!(p->left->o.flags&DREFOBJ)){
  293.             free(new);
  294.             p->o=p->left->o;
  295.             p->o.flags|=DREFOBJ;
  296.             return;
  297.         }
  298.         if(p->left->o.flags&SCRATCH){
  299.             new->z=p->left->o;
  300.             new->z.flags&=~DREFOBJ;
  301.         }else{
  302.             /*  hier muss man noch was aender, da das so nicht funktioniert */
  303.             get_scratch(&new->z,p->left->ntyp->flags,p->ntyp->flags);
  304.         }
  305.         new->code=ASSIGN;new->typf=POINTER;
  306.         new->q1=p->left->o;
  307.         new->q2.val.vlong=sizetab[POINTER];
  308.         p->o=new->z;
  309.         add_IC(new);
  310.         p->o.flags|=DREFOBJ;
  311.         return;
  312.     }
  313.     if(p->flags==ASSIGN){
  314.         new->code=ASSIGN;
  315.         gen_IC(p->right,0,0);
  316.         gen_IC(p->left,0,0);
  317.         convert(p->right,p->ntyp->flags&31);
  318.         new->q1=p->right->o;
  319.         new->z=p->left->o;
  320.         new->q2.val.vlong=szof(p->left->ntyp);
  321.         p->o=new->z;
  322.         add_IC(new);
  323.         return;
  324.     }
  325.     if(p->flags==ASSIGNADD){
  326.     /*  das hier ist nicht besonders schoen */
  327.         struct obj o;struct IC *n;int f;
  328.         if(p->right->right==0){
  329.         /*  sowas wie a+=0 wurde wegoptimiert   */
  330.             free(new);
  331.             p->o=p->left->o;
  332.             return;
  333.         }
  334.         f=do_arith(p->right,new,p->left,&o);
  335.         if(!f) {ierror(0);return;}
  336.         if(f>1) {ierror(0);return;}
  337.         if(!nocode&&(o.flags&(SCRATCH|REG))==(SCRATCH|REG)&&!regs[o.reg]){
  338.         /*  ueberfluessiges FREEREG entfernen   */
  339.             n=last_ic;
  340.             while(n){
  341.                 if(n->code==FREEREG&&n->q1.reg==o.reg){
  342.                     remove_IC(n);if(!nocode) regs[o.reg]=1;
  343.                     break;
  344.                 }
  345.                 n=n->prev;
  346.             }
  347.         }
  348.         convert(p->right,p->ntyp->flags&31);
  349.         new=mymalloc(ICS);
  350.         new->typf=p->ntyp->flags&31;
  351.         new->q2.flags=0;
  352.         new->code=ASSIGN;
  353.         new->q1=p->right->o;
  354.         new->z=o;
  355.         new->q2.val.vlong=szof(p->left->ntyp);
  356.         p->o=new->z;
  357.         add_IC(new);
  358.         return;
  359.     }
  360.     if(p->flags==MINUS||p->flags==KOMPLEMENT){
  361.         new->code=p->flags;
  362.         gen_IC(p->left,0,0);
  363.         convert(p->left,p->ntyp->flags);
  364.         if(regok(p->left->o.reg,p->ntyp->flags,0)&&(p->left->o.flags&SCRATCH)){
  365.             new->z=p->left->o;
  366.             new->z.flags&=~DREFOBJ;
  367.         }else{
  368.             get_scratch(&new->z,p->left->ntyp->flags,0);
  369.         }
  370.         new->q1=p->left->o;
  371.         p->o=new->z;
  372.         add_IC(new);
  373.         return;
  374.     }
  375.     if(p->flags==ADDRESS||p->flags==ADDRESSA||p->flags==ADDRESSS){
  376.         new->code=ADDRESS;
  377.         new->typf=p->left->ntyp->flags&31;
  378.         gen_IC(p->left,0,0);
  379.         if(p->left->o.flags&VAR) p->left->o.v->flags|=USEDASSOURCE|USEDASDEST;
  380.         if(p->left->o.flags&DREFOBJ){
  381.             free(new);
  382.             p->o=p->left->o;
  383.             p->o.flags&=~DREFOBJ;
  384.             return;
  385.         }
  386.         if((p->left->o.flags&VAR)&&!(p->left->o.flags&VARADR)
  387.            &&(p->left->o.v->storage_class==EXTERN||p->left->o.v->storage_class==STATIC)){
  388.             free(new);
  389.             p->o=p->left->o;
  390.             p->o.flags|=VARADR;
  391.             return;
  392.         }
  393.         new->q1=p->left->o;
  394.         get_scratch(&new->z,POINTER,p->ntyp->next->flags);
  395.         p->o=new->z;
  396.         add_IC(new);
  397.         return;
  398.     }
  399.     if(p->flags==LAND||p->flags==LOR){
  400.         int l1,l2,l3,l4;
  401. /*        printf("%s true=%d false=%d\n",ename[p->flags],ltrue,lfalse);*/
  402.         l1=++label;if(!ltrue) {l2=++label;l3=++label;l4=++label;}
  403.         if(!ltrue){if(p->flags==LAND) gen_IC(p->left,l1,l3);
  404.                     else gen_IC(p->left,l3,l1);
  405.         }else     {if(p->flags==LAND) gen_IC(p->left,l1,lfalse);
  406.                     else gen_IC(p->left,ltrue,l1);
  407.         }
  408.         if(p->left->o.flags!=0){
  409.             if(p->flags==LAND)
  410.                 gen_test(&p->left->o,p->left->ntyp->flags,BEQ,((!ltrue)?l3:lfalse));
  411.             else
  412.                 gen_test(&p->left->o,p->left->ntyp->flags,BNE,((!ltrue)?l3:ltrue));
  413.         }
  414.         gen_label(l1);
  415.         if(!ltrue){if(p->flags==LAND) gen_IC(p->right,l2,l3);
  416.                     else gen_IC(p->right,l3,l2);
  417.         }else      gen_IC(p->right,ltrue,lfalse);
  418.         if(p->right->o.flags!=0){
  419.             if(p->flags==LAND)
  420.                 gen_test(&p->right->o,p->right->ntyp->flags,BEQ,((!ltrue)?l3:lfalse));
  421.             else
  422.                 gen_test(&p->right->o,p->right->ntyp->flags,BNE,((!ltrue)?l3:ltrue));
  423.         }
  424.         if(!ltrue){
  425.             gen_label(l2);
  426.             if(p->flags==LAND) p->o=gen_cond(0,l3,l4); else p->o=gen_cond(1,l3,l4);
  427.         }else{
  428.             new=mymalloc(ICS);
  429.             new->code=BRA;
  430.             if(p->flags==LAND) new->typf=ltrue; else new->typf=lfalse;
  431.             add_IC(new);
  432.         }
  433.         if(ltrue) p->o.flags=0;
  434.         return;
  435.     }
  436.     if(p->flags==NEGATION){
  437.         int l1,l2,l3;
  438.         if(!ltrue) {l1=++label;l2=++label;l3=++label;}
  439.         if(ltrue) gen_IC(p->left,lfalse,ltrue); else gen_IC(p->left,l1,l3);
  440.         if(!p->left->o.flags) {free(new);p->o.flags=0;
  441.         }else{
  442.             gen_test(&p->left->o,p->left->ntyp->flags,BNE,((!ltrue)?l1:lfalse));
  443.         }
  444.         if(ltrue){
  445.             new=mymalloc(ICS);
  446.             new->code=BRA;
  447.             if(!ltrue) new->typf=l2; else new->typf=ltrue;
  448.             add_IC(new);
  449.             p->o.flags=0;
  450.         }else{
  451.             gen_label(l3);
  452.             p->o=gen_cond(0,l1,l2);
  453.         }
  454.         return;
  455.     }
  456.     if(p->flags>=EQUAL&&p->flags<=GREATEREQ){
  457.         int l1,l2,l3,tl,tr,swapped;
  458.         if(!ltrue) {l1=++label;l2=++label;l3=++label;}
  459.         if(p->left->flags==CEXPR){
  460.         /*  Konstanten nach rechts  */
  461.             np merk;merk=p->left;p->left=p->right;p->right=merk;
  462.             swapped=1;
  463.         }else swapped=0;
  464.         new->code=COMPARE;
  465.         tl=p->left->ntyp->flags&31;tr=p->right->ntyp->flags&31;
  466.         if(p->right->flags==CEXPR&&(tr&15)<FLOAT&&(tl&15)<FLOAT){
  467.             int negativ;
  468.             eval_constn(p->right);
  469.             if(zlleq(vlong,0)) negativ=1; else negativ=0;
  470.             if((tl&UNSIGNED)||(tr&UNSIGNED)) negativ=0;
  471.             if((!negativ||zlleq(t_min[tl],vlong))&&(negativ||zulleq(vulong,t_max[tl]))){
  472.                 convert(p->right,tl);
  473.                 tr=tl;
  474.             }
  475.         }
  476.         if(arith(tl&15)&&(tl!=tr||!shortcut(COMPARE,tl))){
  477.             struct Typ *t;
  478.             t=arith_typ(p->left->ntyp,p->right->ntyp);
  479.             new->typf=t->flags&31;
  480.             freetyp(t);
  481.         }else{
  482.             new->typf=p->left->ntyp->flags&31;
  483.         }
  484.         gen_IC(p->left,0,0);
  485.         convert(p->left,new->typf);
  486.         gen_IC(p->right,0,0);
  487.         convert(p->right,new->typf);
  488.         new->q1=p->left->o;
  489.         new->q2=p->right->o;
  490.         new->z.flags=0;
  491.         add_IC(new);
  492.         new=mymalloc(ICS);
  493.         if(p->flags==EQUAL) new->code=BEQ;
  494.         if(p->flags==INEQUAL) new->code=BNE;
  495.         if(p->flags==LESS) {if(swapped) new->code =BGT; else new->code=BLT;}
  496.         if(p->flags==LESSEQ){if(swapped) new->code=BGE; else new->code=BLE;}
  497.         if(p->flags==GREATER){if(swapped) new->code=BLT; else new->code=BGT;}
  498.         if(p->flags==GREATEREQ){if(swapped) new->code=BLE; else new->code=BGE;}
  499.         if(ltrue) new->typf=ltrue; else new->typf=l1;
  500.         add_IC(new);
  501.         if(ltrue){
  502.             new=mymalloc(ICS);
  503.             new->code=BRA;
  504.             new->typf=lfalse;
  505.             add_IC(new);
  506.             p->o.flags=0;
  507.         }else{
  508.             gen_label(l3);
  509.             p->o=gen_cond(1,l1,l2);
  510.         }
  511.         return;
  512.     }
  513.     if(p->flags==CALL){
  514.         int r=0;struct obj *op;zlong sz;
  515.         function_calls+=currentpri;
  516.         if(p->left->flags==ADDRESS&&p->left->left->flags==IDENTIFIER){
  517.             struct Var *v;
  518.             gen_IC(p->left,0,0); r=1;
  519.             v=p->left->o.v;
  520.             if(v->fi&&v->fi->first_ic&&(c_flags_val[0].l&4096)){
  521.             /*  function call inlining  */
  522.                 struct argument_list *al;
  523.                 struct Var *vp,**argl1,**argl2;
  524.                 struct IC *ip;int lc;
  525.                 int arg_cnt=0,i;
  526.                 if(DEBUG&1024){
  527.                     printf("inlining call to <%s>\n",v->identifier);
  528.                     for(vp=v->fi->vars;vp;vp=vp->next)
  529.                         printf("%s(%ld)\n",vp->identifier,zl2l(vp->offset));
  530.                 }
  531.                 for(vp=v->fi->vars;vp;vp=vp->next){
  532.                     if(zleqto(vp->offset,l2zl(0L))&&*vp->identifier&&(vp->storage_class==AUTO||vp->storage_class==REGISTER)) arg_cnt++;
  533.                 }
  534.  
  535.                 /*  Argumente in die ersten Parametervariablen kopieren */
  536.                 argl1=mymalloc(arg_cnt*sizeof(struct Var *));
  537.                 argl2=mymalloc(arg_cnt*sizeof(struct Var *));
  538.  
  539.                 al=p->alist;vp=v->fi->vars;i=0;
  540.                 while(al){
  541.                     while(vp&&(!*vp->identifier||!zleqto(vp->offset,l2zl(0L))||(vp->storage_class!=REGISTER&&vp->storage_class!=AUTO))) vp=vp->next;
  542.                     if(!vp){ error(39); break; }
  543.                     if(i>=arg_cnt) ierror(0);
  544.                     if(DEBUG&1024) printf("arg: %s(%ld)\n",vp->identifier,zl2l(vp->offset));
  545.                     argl1[i]=vp;
  546.                     argl2[i]=add_var(empty,clone_typ(vp->vtyp),vp->storage_class,0);
  547.                     if(!al->arg) ierror(0);
  548.                     gen_IC(al->arg,0,0);
  549.                     convert(al->arg,vp->vtyp->flags);
  550.                     new=mymalloc(ICS);
  551.                     new->code=ASSIGN;
  552.                     new->q1=al->arg->o;
  553.                     new->q2.flags=0;
  554.                     new->q2.val.vlong=szof(vp->vtyp);
  555.                     new->z.flags=VAR;
  556.                     new->z.val.vlong=l2zl(0L);
  557.                     new->z.v=argl2[i];
  558.                     new->typf=vp->vtyp->flags;
  559.                     add_IC(new);
  560.                     i++;
  561.                     al=al->next;
  562.                     vp=vp->next;
  563.                 }
  564.                 if(i<arg_cnt){ error(83); arg_cnt=i;}
  565.  
  566.                 /*  Kopien der Variablen erzeugen   */
  567.                 for(vp=v->fi->vars;vp;vp=vp->next){
  568.                     vp->inline_copy=0;
  569.                 }
  570.                 for(i=0;i<arg_cnt;i++){
  571.                     if(argl1[i]){
  572.                         if(!argl2[i]) ierror(0);
  573.                         argl1[i]->inline_copy=argl2[i];
  574.                     }
  575.                 }
  576.  
  577.                 /*  Rueckgabewert   */
  578.                 if((p->ntyp->flags&15)!=VOID){
  579.                     p->o.flags=SCRATCH|VAR;
  580.                     p->o.reg=0;p->o.val.vlong=l2zl(0L);
  581.                     p->o.v=add_var(empty,clone_typ(p->ntyp),AUTO,0);
  582.                 }else{
  583.                     p->o.flags=0;
  584.                 }
  585.  
  586.                 free(argl1);
  587.                 free(argl2);
  588.  
  589.                 /*  Code einfuegen und Labels umschreiben   */
  590.                 ip=v->fi->first_ic;lc=0;
  591.                 while(ip){
  592.                     struct Var *iv;
  593.                     int c;
  594.                     new=mymalloc(ICS);
  595.                     memcpy(new,ip,ICS);
  596.                     c=ip->code;
  597.                     /*  evtl. ist ein IC praktisch ein SETRETURN, falls das */
  598.                     /*  Rueckgabeziel ueber Parameterzeiger angespr. wird   */
  599.                     if(ip->z.flags&VAR){
  600.                         iv=ip->z.v;
  601.                         if(iv->storage_class==AUTO||iv->storage_class==REGISTER){
  602.                             if(!*iv->identifier&&zleqto(iv->offset,l2zl(0L))){
  603.                                 new->z=p->o;
  604.                             }else{
  605.                                 if(!iv->inline_copy)
  606.                                     iv->inline_copy=add_var(empty,clone_typ(iv->vtyp),iv->storage_class,0);
  607.                                 new->z.v=iv->inline_copy;
  608.                             }/*else if(iv->inline_copy) ierror(0);*/
  609.                         }
  610.                     }
  611.                     /*  Kopien aller auto/register Variablen erzeugen   */
  612.                     if(ip->q1.flags&VAR){
  613.                         iv=ip->q1.v;
  614.                         if(iv->storage_class==AUTO||iv->storage_class==REGISTER){
  615.                             if(!iv->inline_copy)
  616.                                 iv->inline_copy=add_var(empty,clone_typ(iv->vtyp),iv->storage_class,0);
  617.                             new->q1.v=iv->inline_copy;
  618.                         }/*else if(iv->inline_copy) ierror(0);*/
  619.                     }
  620.                     if(ip->q2.flags&VAR){
  621.                         iv=ip->q2.v;
  622.                         if(iv->storage_class==AUTO||iv->storage_class==REGISTER){
  623.                             if(!iv->inline_copy)
  624.                                 iv->inline_copy=add_var(empty,clone_typ(iv->vtyp),iv->storage_class,0);
  625.                             new->q2.v=iv->inline_copy;
  626.                         }/*else if(iv->inline_copy) ierror(0);*/
  627.                     }
  628.                     if(c==LABEL||(c>=BEQ&&c<=BRA)){
  629.                         if(new->typf>lc) lc=new->typf;
  630.                         new->typf+=label;
  631.                     }
  632.                     if(c==SETRETURN){
  633.                         new->code=ASSIGN;
  634.                         new->z=p->o;
  635.                     }
  636.                     add_IC(new);
  637.                     ip=ip->next;
  638.                 }
  639.                 label+=lc;
  640.                 return;
  641.             }
  642.             /*  einige spezielle Inline-Funktionen; das setzt voraus, dass  */
  643.             /*  diese in den Headerfiles passend deklariert werden          */
  644.             if(v->storage_class==EXTERN){
  645.                 if(!strcmp(v->identifier,"strlen")&&p->alist&&p->alist->arg){
  646.                     np n=p->alist->arg;
  647.                     if(n->flags==ADDRESSA&&n->left->flags==STRING){
  648.                         struct const_list *cl;zulong len=ul2zul(0UL);
  649.                         cl=(struct const_list *)n->left->identifier;
  650.                         while(cl){
  651.                             if(zleqto(l2zl(0L),zc2zl(cl->other->val.vchar))) break;
  652.                             len=zuladd(len,ul2zul(1UL));
  653.                             cl=cl->next;
  654.                         }
  655.                         p->o.val.vulong=len;
  656.                         eval_const(&p->o.val,UNSIGNED|LONG);
  657.                         insert_const(p);
  658.                         insert_const2(&p->o.val,p->ntyp->flags);
  659.                         p->flags=CEXPR;
  660.                         p->o.flags=KONST;
  661.                         return;
  662.                     }
  663.                 }
  664.  
  665.                 if(INLINEMEMCPY>0&&(c_flags_val[0].l&2)){
  666.                     if(!strcmp(v->identifier,"strcpy")&&p->alist&&p->alist->next&&p->alist->next->arg){
  667.                         np n=p->alist->next->arg;
  668.                         if(n->flags==ADDRESSA&&n->left->flags==STRING){
  669.                             struct const_list *cl;zlong len=l2zl(0L);
  670.                             cl=(struct const_list *)n->left->identifier;
  671.                             while(cl){
  672.                                 len=zladd(len,l2zl(1L));
  673.                                 if(zleqto(zc2zl(cl->other->val.vchar),l2zl(0L))) break;
  674.                                 cl=cl->next;
  675.                             }
  676.                             if(zlleq(len,l2zl((long)INLINEMEMCPY))){
  677.                                 inline_memcpy(p->alist->arg,n,len);
  678.                                 p->o=p->alist->arg->o;
  679.                                 return;
  680.                             }
  681.                         }
  682.                     }
  683.                     if(!strcmp(v->identifier,"memcpy")){
  684.                         if(p->alist&&p->alist->next&&p->alist->next->next
  685.                            &&p->alist->next->next->arg
  686.                            &&p->alist->next->next->arg->flags==CEXPR){
  687.                             eval_constn(p->alist->next->next->arg);
  688.                             if(zlleq(vlong,l2zl((long)INLINEMEMCPY))){
  689.                                 inline_memcpy(p->alist->arg,p->alist->next->arg,vlong);
  690.                                 p->o=p->alist->arg->o;
  691.                                 return;
  692.                             }
  693.                         }
  694.                     }
  695.                 }
  696.             }
  697.         }
  698.         rl=0;
  699.         sz=push_args(p->alist,p->left->ntyp->next->exact,0,&rl);
  700.         if(!r) gen_IC(p->left,0,0);
  701.         if(!(p->left->o.flags&DREFOBJ)){
  702.             free(new);
  703.             p->o=p->left->o;
  704.             if(p->o.flags&VARADR) p->o.flags&=~VARADR;
  705.              else p->o.flags|=DREFOBJ;
  706.         }else{
  707.             if(p->left->o.flags&VARADR){
  708.                 free(new);
  709.                 p->o=p->left->o;
  710.                 p->o.flags&=~VARADR;
  711.             }else{
  712.                 if(p->left->o.flags&SCRATCH){
  713.                     new->z=p->left->o;
  714.                     new->z.flags&=~DREFOBJ;
  715.                 }else{
  716.                 /* das hier funktioniert vermutlich auch nicht  */
  717.                     get_scratch(&new->z,p->left->ntyp->flags,p->ntyp->flags);
  718.                 }
  719.                 new->code=ASSIGN;new->typf=POINTER;
  720.                 new->q1=p->left->o;
  721.                 new->q2.val.vlong=sizetab[POINTER];
  722.                 new->q2.flags=0;
  723.                 p->o=new->z;
  724.                 add_IC(new);
  725.                 p->o.flags|=DREFOBJ;
  726.             }
  727.         }
  728. /*            p->left->o.flags-=DREFOBJ|VARADR; Was sollte das??    */
  729.  
  730.         if(c_flags_val[0].l&2){
  731.             while(rl){
  732.                 struct regargs_list *m;
  733.                 new=mymalloc(ICS);
  734.                 new->code=NOP;
  735.                 new->q1.flags=VAR;
  736.                 new->q1.v=rl->v;
  737.                 new->q1.val.vlong=l2zl(0L);
  738.                 new->typf=0;
  739.                 new->q2.flags=new->z.flags=0;
  740.                 add_IC(new);
  741.                 m=rl->next;free(rl);rl=m;
  742.             }
  743.         }
  744.         /*  gegebenenfalls Adresse des Ziels auf den Stack  */
  745.         if(!freturn(p->ntyp)){
  746.             struct obj o;
  747.             new=mymalloc(ICS);
  748.             new->code=ADDRESS;
  749.             new->typf=p->ntyp->flags&31;
  750.             new->q1.flags=VAR;
  751.             new->q1.v=add_var(empty,clone_typ(p->ntyp),AUTO,0);
  752.             new->q1.val.vlong=l2zl(0L);
  753.             op=&new->q1;
  754.             new->q2.flags=0;
  755.             get_scratch(&new->z,POINTER,p->ntyp->flags&31);
  756.             o=new->z;
  757.             add_IC(new);
  758.             new=mymalloc(ICS);
  759.             new->code=PUSH;
  760.             new->typf=POINTER;
  761.             new->q1=o;
  762.             new->q2.flags=new->z.flags=0;
  763.             new->q2.val.vlong=sizetab[POINTER];
  764.             add_IC(new);
  765.             sz=zladd(sz,sizetab[POINTER]);
  766.         }
  767.         /*  Scratchregister evtl. sichern   */
  768.         savescratch(MOVEFROMREG,last_ic,0);
  769.         new=mymalloc(ICS);
  770.         new->code=CALL;
  771.         new->typf=FUNKT;
  772.         new->q1=p->o;
  773.         new->q2.flags=new->z.flags=0;
  774.         new->q2.val.vlong=sz; /*  Groesse der Parameter auf dem Stack */
  775.         add_IC(new);
  776.         r=0;
  777.         if((p->ntyp->flags&15)!=VOID){
  778.             new=mymalloc(ICS);
  779.             new->code=GETRETURN;
  780.             new->q1.flags=new->q2.flags=0;
  781.             new->q1.reg=freturn(p->ntyp);
  782.             new->q2.val.vlong=szof(p->ntyp);
  783.             new->typf=p->ntyp->flags;
  784.             if(freturn(p->ntyp)){
  785.                 int t=p->ntyp->flags&15;
  786.                 if(t==STRUCT||t==UNION){
  787.                     new->z.v=add_var(empty,clone_typ(p->ntyp),AUTO,0);
  788.                     new->z.flags=VAR;
  789.                     new->z.val.vlong=l2zl(0L);
  790.                 }else get_scratch(&new->z,p->ntyp->flags&31,0);
  791.             } else new->z=*op;
  792.             if((new->z.flags&(REG|DREFOBJ))==REG) r=new->z.reg;
  793.             p->o=new->z;
  794.             add_IC(new);
  795.         }else{
  796.             p->o.flags=0;
  797.         }
  798.         /*  Scratchregister evtl. wiederherstellen  */
  799.         savescratch(MOVETOREG,last_ic,r);
  800.         /*  Evtl. gespeicherte Registerargumente wiederherstellen.  */
  801.         while(rl){
  802.             struct regargs_list *m;
  803.             if(rl->v){
  804.                 new=mymalloc(ICS);
  805.                 new->code=MOVETOREG;
  806.                 new->typf=0;
  807.                 new->q1.flags=VAR;
  808.                 new->q1.v=rl->v;
  809.                 new->q1.val.vlong=l2zl(0L);
  810.                 new->z.flags=REG;
  811.                 new->z.reg=rl->reg;
  812.                 new->q2.flags=0;
  813.                 new->q2.val.vlong=regsize[rl->reg];
  814.                 add_IC(new);
  815.             }else{
  816.                 new=mymalloc(ICS);
  817.                 new->code=FREEREG;
  818.                 new->typf=0;
  819.                 new->q1.flags=REG;
  820.                 new->q2.flags=new->z.flags=0;
  821.                 new->q1.reg=rl->reg;
  822.                 add_IC(new);
  823.                 regs[rl->reg]=0;
  824.             }
  825.             m=rl->next;free(rl);rl=m;
  826.         }
  827.         return;
  828.     }
  829.     if(p->flags>=PREINC&&p->flags<=POSTDEC){
  830.         struct obj o;
  831.         gen_IC(p->left,0,0);
  832.         if(p->flags==POSTINC||p->flags==POSTDEC){
  833.             new=mymalloc(ICS);
  834.             new->code=ASSIGN;
  835.             new->typf=p->ntyp->flags&31;
  836.             new->q2.val.vlong=sizetab[p->ntyp->flags&15];
  837.             new->q1=p->left->o;
  838.             new->q1.flags&=~SCRATCH;
  839.             get_scratch(&new->z,p->left->ntyp->flags&31,0);
  840.             new->q2.flags=0;
  841.             o=new->z;
  842.             add_IC(new);
  843.             new=mymalloc(ICS);
  844.         }else o=p->left->o;
  845.         if((p->left->ntyp->flags&15)==POINTER){
  846.             if(p->flags==PREINC||p->flags==POSTINC) new->code=ADDI2P; else new->code=SUBIFP;
  847.             vlong=szof(p->left->ntyp->next);
  848.             new->q2.val.vint=zl2zi(vlong);
  849.             new->typf=INT;
  850.             new->q1=p->left->o;
  851.             new->z=p->left->o;
  852.             new->q2.flags=KONST;
  853.             add_IC(new);
  854.         }else{
  855.             if(p->flags==PREINC||p->flags==POSTINC) new->code=ADD; else new->code=SUB;
  856.             new->typf=p->ntyp->flags&31;
  857.             new->q1=p->left->o;
  858.             new->z=p->left->o;
  859.             new->q2.flags=KONST;
  860.             vlong=l2zl(1L);vulong=zl2zul(vlong);vdouble=zl2zd(vlong);
  861.             if(new->typf==CHAR) new->q2.val.vchar=zl2zc(vlong);
  862.             if(new->typf==SHORT) new->q2.val.vshort=zl2zs(vlong);
  863.             if(new->typf==INT) new->q2.val.vint=zl2zi(vlong);
  864.             if(new->typf==LONG) new->q2.val.vlong=vlong;
  865.             if(new->typf==(UNSIGNED|CHAR)) new->q2.val.vuchar=zul2zuc(vulong);
  866.             if(new->typf==(UNSIGNED|SHORT)) new->q2.val.vushort=zul2zus(vulong);
  867.             if(new->typf==(UNSIGNED|INT)) new->q2.val.vuint=zul2zui(vulong);
  868.             if(new->typf==(UNSIGNED|LONG)) new->q2.val.vulong=vulong;
  869.             if(new->typf==DOUBLE) new->q2.val.vdouble=vdouble;
  870.             if(new->typf==FLOAT) new->q2.val.vfloat=zd2zf(vdouble);
  871.             add_IC(new);
  872.         }
  873.         if(p->flags==POSTINC||p->flags==POSTDEC){
  874.             if(p->left->o.flags&SCRATCH) free_reg(p->left->o.reg);
  875.         }
  876.         p->o=o;
  877.         return;
  878.     }
  879.     if(p->flags==COND){
  880.         int ltrue,lfalse,lout;
  881.         ltrue=++label;lfalse=++label;lout=++label;
  882.         gen_IC(p->left,ltrue,lfalse);
  883.         if(!p->left->o.flags){
  884.             free(new);
  885.         }else{
  886.             if(p->left->flags!=CEXPR){
  887.                 gen_test(&p->left->o,p->left->ntyp->flags,BEQ,lfalse);
  888.             }else{
  889.                 eval_constn(p->left);
  890.                 if(zleqto(vlong,l2zl(0L))&&zuleqto(vulong,ul2zul(0UL))&&zdeqto(vdouble,d2zd(0.0))){
  891.                     gen_IC(p->right->right,0,0);
  892.                     p->o=p->right->right->o;
  893.                 }else{
  894.                     gen_IC(p->right->left,0,0);
  895.                     p->o=p->right->left->o;
  896.                 }
  897.                 return;
  898.             }
  899.         }
  900.         gen_label(ltrue);
  901.         gen_IC(p->right->left,0,0);
  902.         convert(p->right->left,p->ntyp->flags&31);
  903.         if((p->right->left->o.flags&(SCRATCH|DREFOBJ))==SCRATCH){
  904.             p->o=p->right->left->o;
  905.         }else{
  906.             get_scratch(&p->o,p->ntyp->flags&31,0);
  907.             new=mymalloc(ICS);
  908.             new->code=ASSIGN;
  909.             new->q1=p->right->left->o;
  910.             new->z=p->o;
  911.             new->q2.flags=0;
  912.             new->q2.val.vlong=szof(p->ntyp);
  913.             new->typf=p->ntyp->flags&31;
  914.             p->o=new->z;
  915.             add_IC(new);
  916.         }
  917.         new=mymalloc(ICS);
  918.         new->code=BRA;
  919.         new->typf=lout;
  920.         add_IC(new);
  921.         gen_label(lfalse);
  922.         gen_IC(p->right->right,0,0);
  923.         convert(p->right->right,p->ntyp->flags&31);
  924.         new=mymalloc(ICS);
  925.         new->code=ASSIGN;
  926.         new->q1=p->right->right->o;
  927.         new->z=p->o;
  928.         new->q2.flags=0;
  929.         new->q2.val.vlong=szof(p->ntyp);
  930.         new->typf=p->ntyp->flags&31;
  931.         add_IC(new);
  932.         gen_label(lout);
  933.         return;
  934.     }
  935.     printf("Operation: %d=%s\n",p->flags,ename[p->flags]);
  936.     ierror(0);
  937.     free(new);
  938.     p->o.flags=0;
  939. }
  940. zlong push_args(struct argument_list *al,struct struct_declaration *sd,int n,struct regargs_list **rl)
  941. /*  Legt die Argumente eines Funktionsaufrufs in umgekehrter Reihenfolge    */
  942. /*  auf den Stack. Es wird Integer-Erweiterung vorgenommen und float wird   */
  943. /*  nach double konvertiert, falls kein Prototype da ist. Ausserdem werden  */
  944. /*  alle Argumente in ihrer Groesse aligned. Das ist evtl. nicht fuer jede  */
  945. /*  CPU ausreichend. Hier muss evtl. noch etwas getan werden.               */
  946. {
  947.     int t,reg;struct IC *new;struct regargs_list *nrl;zlong sz,of;
  948.     if(!al) return(0);
  949.     if(al->next) of=push_args(al->next,sd,n+1,rl); else of=l2zl(0L);
  950.     if(!al->arg) {ierror(0);return(of);}
  951.     if(!sd) {ierror(0);return(of);}
  952.     gen_IC(al->arg,0,0);
  953.     if(n<sd->count){
  954.         t=(*sd->sl)[n].styp->flags;sz=szof((*sd->sl)[n].styp);
  955.         reg=(*sd->sl)[n].reg;
  956.     }else{
  957.         reg=0;
  958.         t=al->arg->ntyp->flags;sz=szof(al->arg->ntyp);
  959.     }
  960.     if((t&15)>=CHAR&&(t&15)<=LONG) {t=int_erw(t);sz=sizetab[t&15];}
  961.     if((t&15)==FLOAT&&n>=sd->count) {t=DOUBLE;sz=sizetab[t];}
  962.     convert(al->arg,t&31);
  963.     if(reg==0){
  964.         /*  Parameteruebergabe ueber Stack. */
  965.         new=mymalloc(ICS);
  966.         new->code=PUSH;
  967.         new->typf=t;
  968.         new->q1=al->arg->o;
  969.         new->q2.flags=new->z.flags=0;
  970.         new->q2.val.vlong=zlmult(zldiv(zladd(sz,zlsub(maxalign,l2zl(1L))),maxalign),maxalign);
  971.         add_IC(new);
  972.         return(zladd(of,sz));
  973.     }else{
  974.         /*  Parameteruebergabe in Register. */
  975.         struct Var *v=0; struct Typ *t2;
  976.         if(c_flags_val[0].l&2){
  977.         /*  Version fuer Optimizer. */
  978.             t2=mymalloc(TYPS);
  979.             t2->flags=t;
  980.             if((t&15)==POINTER){
  981.                 t2->next=mymalloc(TYPS);
  982.                 t2->next->flags=VOID;
  983.                 t2->next->next=0;
  984.             }else t2->next=0;
  985.             v=add_var(empty,t2,AUTO,0);
  986.             new=mymalloc(ICS);
  987.             new->code=ASSIGN;
  988.             new->typf=t;
  989.             new->q1=al->arg->o;
  990.             new->q2.flags=0;
  991.             new->q2.val.vlong=sz;
  992.             new->z.flags=VAR;
  993.             new->z.v=v;
  994.             new->z.val.vlong=l2zl(0L);
  995.             add_IC(new);
  996.             nrl=mymalloc(sizeof(*nrl));
  997.             nrl->next=*rl;
  998.             nrl->reg=reg;
  999.             nrl->v=v;
  1000.             *rl=nrl;
  1001.             if(n==0){
  1002.             /*  Letztes Argument; jetzt in Register laden.  */
  1003.                 for(;nrl;nrl=nrl->next){
  1004.                     new=mymalloc(ICS);
  1005.                     new->code=ASSIGN;
  1006.                     new->typf=nrl->v->vtyp->flags|VOLATILE;
  1007.                     new->q1.flags=VAR;
  1008.                     new->q1.v=nrl->v;
  1009.                     new->q1.val.vlong=l2zl(0L);
  1010.                     new->q2.flags=0;
  1011.                     new->q2.val.vlong=szof(nrl->v->vtyp);
  1012.                     new->z.flags=VAR;
  1013.                     new->z.val.vlong=l2zl(0L);
  1014.                     new->z.v=add_var(empty,clone_typ(nrl->v->vtyp),AUTO,0);
  1015.                     new->z.v->reg=nrl->reg;
  1016.                     nrl->v=new->z.v;
  1017.                     add_IC(new);
  1018.                 }
  1019.             }
  1020.             return(of);
  1021.         }else{
  1022.         /*  Nicht-optimierende Version. */
  1023.             if(!regs[reg]){
  1024.                 new=mymalloc(ICS);
  1025.                 new->code=ALLOCREG;
  1026.                 new->typf=0;
  1027.                 new->q1.flags=REG;
  1028.                 new->q1.reg=reg;
  1029.                 new->q2.flags=new->z.flags=0;
  1030.                 add_IC(new);
  1031.                 regs[reg]=33;regused[reg]++;
  1032.             }else{
  1033.                 if(al->arg->o.flags!=(REG|SCRATCH)||al->arg->o.reg!=reg){
  1034.                     t2=mymalloc(TYPS);
  1035.                     t2->flags=ARRAY;
  1036.                     t2->size=regsize[reg];
  1037.                     t2->next=mymalloc(TYPS);
  1038.                     t2->next->flags=CHAR;
  1039.                     t2->next->next=0;
  1040.                     v=add_var(empty,t2,AUTO,0);
  1041.                     new=mymalloc(ICS);
  1042.                     new->code=MOVEFROMREG;
  1043.                     new->typf=0;
  1044.                     new->q1.flags=REG;
  1045.                     new->q1.reg=reg;
  1046.                     new->q2.flags=0;
  1047.                     new->q2.val.vlong=regsize[reg];
  1048.                     new->z.flags=VAR;
  1049.                     new->z.v=v;
  1050.                     new->z.val.vlong=l2zl(0L);
  1051.                     add_IC(new);
  1052.                 }else regs[reg]|=32;
  1053.             }
  1054.             new=mymalloc(ICS);
  1055.             new->code=ASSIGN;
  1056.             new->typf=t;
  1057.             new->q1=al->arg->o;
  1058.             new->q2.flags=new->z.flags=0;
  1059.             new->q2.val.vlong=sz;
  1060.             new->z.flags=REG;
  1061.             new->z.reg=reg;
  1062.             add_IC(new);
  1063.             nrl=mymalloc(sizeof(*nrl));
  1064.             nrl->next=*rl;
  1065.             nrl->reg=reg;
  1066.             nrl->v=v;
  1067.             *rl=nrl;
  1068.             return(of);
  1069.         }
  1070.     }
  1071. }
  1072.  
  1073. void convert(np p,int f)
  1074. /*  konvertiert das Objekt in p->o in bestimmten Typ    */
  1075. {
  1076.     struct IC *new;
  1077.     if((f&15)==VOID||(p->ntyp->flags&31)==f) return;
  1078.     if(p->flags==CEXPR||p->flags==PCEXPR){
  1079.         eval_constn(p);
  1080.         p->ntyp->flags=f;
  1081.         insert_const(p);
  1082.         p->o.val=p->val;
  1083.         return;
  1084.     }
  1085.     if(!must_convert(p,f)) return;
  1086.     new=mymalloc(ICS);
  1087.     new->q1=p->o;
  1088.     new->q2.flags=0;
  1089.     new->code=CONVCHAR+(p->ntyp->flags&15)-CHAR;
  1090.     if(p->ntyp->flags&UNSIGNED) new->code+=8;
  1091.     new->typf=f;
  1092.     if(!regok(p->o.reg,f,0)||!(p->o.flags&SCRATCH)){
  1093.         get_scratch(&new->z,f,0);
  1094.         p->o=new->z;
  1095.         add_IC(new);
  1096.     }else{
  1097.         new->z=p->o;new->z.flags&=~DREFOBJ;
  1098.         p->o=new->z;
  1099.         add_IC(new);
  1100.     }
  1101. }
  1102.  
  1103. int allocreg(int f,int mode)
  1104. /*  Fordert Register fuer Typ f an                      */
  1105. /*  evtl. maschinenabhaengig, aber hier fehlt noch viel */
  1106. /*  z.B. Eintragen eines IC                             */
  1107. {
  1108.     int i;struct IC *new;
  1109.     if(nocode) return(1);
  1110.     for(i=1;i<=MAXR;i++){
  1111.         if(!regs[i]&®ok(i,f,mode)){
  1112.             if(DEBUG&16) printf("alocated %s\n",regnames[i]);
  1113.             regs[i]=1;regused[i]++;
  1114.             new=mymalloc(ICS);
  1115.             new->code=ALLOCREG;
  1116.             new->typf=0;
  1117.             new->q1.flags=REG;
  1118.             new->q1.reg=i;
  1119.             new->q2.flags=new->z.flags=0;
  1120.             add_IC(new);
  1121.             return(i);
  1122.         }
  1123.     }
  1124.     if(DEBUG&1) printf(">%sCouldn't allocate register for type %d\n",string,f);
  1125.     return(0);
  1126. }
  1127. void free_reg(int r)
  1128. /*  Gibt Register r frei                                */
  1129. /*  Eintrag eines IC fehlt noch                         */
  1130. {
  1131.     struct IC *new;
  1132.     if(!r||nocode) return;
  1133.     if(regs[r]==0) {printf("Register %s:\n",regnames[r]);ierror(0);}
  1134.     if(DEBUG&16) printf("freed %s\n",regnames[r]);
  1135.     new=mymalloc(ICS);
  1136.     new->code=FREEREG;
  1137.     new->typf=0;
  1138.     new->q1.flags=REG;
  1139.     new->q1.reg=r;
  1140.     new->q2.flags=new->z.flags=0;
  1141.     add_IC(new);
  1142.     regs[r]=0;
  1143. }
  1144. void gen_label(int l)
  1145. /*  Erzeugt ein Label                                   */
  1146. {
  1147.     struct IC *new;
  1148.     new=mymalloc(ICS);
  1149.     new->code=LABEL;
  1150.     new->typf=l;
  1151.     new->q1.flags=new->q2.flags=new->z.flags=0;
  1152.     add_IC(new);
  1153. }
  1154. struct obj gen_cond(int m,int l1,int l2)
  1155. /*  Generiert code, der 0 oder 1 in Register schreibt   */
  1156. {
  1157.     struct IC *new;
  1158.     struct obj omerk;
  1159.     new=mymalloc(ICS);
  1160.     new->code=ASSIGN;
  1161.     new->typf=INT;
  1162.     new->q1.flags=KONST;
  1163.     new->q2.flags=0;
  1164.     new->q2.val.vlong=sizetab[INT];
  1165.     if(!m) vlong=l2zl(1L); else vlong=l2zl(0L);
  1166.     new->q1.val.vint=zl2zi(vlong);
  1167.     get_scratch(&new->z,INT,0);
  1168.     omerk=new->z;
  1169.     add_IC(new);
  1170.     new=mymalloc(ICS);
  1171.     new->code=BRA;
  1172.     new->typf=l2;
  1173.     add_IC(new);
  1174.     gen_label(l1);
  1175.     new=mymalloc(ICS);
  1176.     new->code=ASSIGN;
  1177.     new->typf=INT;
  1178.     new->q1.flags=KONST;
  1179.     new->q2.flags=0;
  1180.     new->q2.val.vlong=sizetab[INT];
  1181.     if(!m) vlong=l2zl(0L); else vlong=l2zl(1L);
  1182.     new->q1.val.vint=zl2zi(vlong);
  1183.     new->z=omerk;
  1184. /*    new->z.reg=r;
  1185.     new->z.flags=SCRATCH|REG;*/
  1186.     add_IC(new);
  1187.     gen_label(l2);
  1188.     return(omerk);
  1189. }
  1190. void scratch_var(struct obj *o,int t)
  1191. /*  liefert eine temporaere Variable                            */
  1192. /*  nicht effizient, aber wer hat schon so wenig Register...    */
  1193. {
  1194.     struct Typ *nt=mymalloc(TYPS);
  1195.     if((t&15)<CHAR||(t&15)>POINTER) ierror(0);
  1196.     nt->flags=t&31;
  1197.     if((t&15)==POINTER){
  1198.         nt->next=mymalloc(TYPS);
  1199.         nt->next->flags=VOID;
  1200.         nt->next->next=0;
  1201.     }else nt->next=0;
  1202.     o->flags=SCRATCH|VAR;o->reg=0;
  1203.     o->v=add_var(empty,nt,AUTO,0);
  1204.     o->val.vlong=l2zl(0L);
  1205. }
  1206. void get_scratch(struct obj *o,int t1,int t2)
  1207. /*  liefert ein Scratchregister oder eine Scratchvariable       */
  1208. {
  1209.     if(!(c_flags_val[0].l&2)&&(o->reg=allocreg(t1,t2))){
  1210.         o->flags=SCRATCH|REG;
  1211.     }else{
  1212.         scratch_var(o,t1);
  1213.     }
  1214. }
  1215. void remove_IC(struct IC *p)
  1216. /*  entfernt IC p aus Liste */
  1217. {
  1218.     if(p->prev) p->prev->next=p->next; else first_ic=p->next;
  1219.     if(p->next) p->next->prev=p->prev; else last_ic=p->prev;
  1220.     if(p->q1.am) free(p->q1.am);
  1221.     if(p->q2.am) free(p->q2.am);
  1222.     if(p->z.am) free(p->z.am);
  1223.     free(p);
  1224. }
  1225. int do_arith(np p,struct IC *new,np dest,struct obj *o)
  1226. /*  erzeugt IC new fuer einen arithmetischen Knoten und speichert das   */
  1227. /*  Resultat vom Unterknoten dest in o (fuer a op= b)               */
  1228. /*  liefert 0, wenn dest nicht gefunden                             */
  1229. {
  1230.     int f=0;
  1231.     new->code=p->flags;
  1232.     if(new->code==PMULT) new->code=MULT;
  1233.     gen_IC(p->left,0,0);
  1234.     if(dest&&p->left==dest) {*o=p->left->o;f++;}
  1235.     gen_IC(p->right,0,0);
  1236.     if(dest&&p->right==dest) {*o=p->right->o;f++;}
  1237.  
  1238.     if((p->left->ntyp->flags&15)==POINTER&&(p->right->ntyp->flags&15)==POINTER){
  1239.     /*  Subtrahieren zweier Pointer                                 */
  1240.         if(p->flags!=SUB) ierror(0);
  1241.         new->typf=INT;
  1242.         new->code=SUBPFP;
  1243.         new->q1=p->left->o;
  1244.         new->q2=p->right->o;
  1245.         if(!dest&&p->left->o.flags&SCRATCH&®ok(p->left->o.reg,INT,0)){
  1246.             new->z=p->left->o;
  1247.             new->z.flags&=~DREFOBJ;
  1248.         }else{
  1249.             if(USEQ2ASZ&&(p->right->o.flags&SCRATCH)&®ok(p->right->o.reg,INT,0)){
  1250.                 new->z=p->left->o;
  1251.                 new->z.flags&=(~DREFOBJ);
  1252.             }else{
  1253.                 get_scratch(&new->z,INT,0);
  1254.             }
  1255.         }
  1256.         p->o=new->z;
  1257.         add_IC(new);
  1258.         if(!zlleq(szof(p->left->ntyp->next),l2zl(1L))){
  1259.             new=mymalloc(ICS);
  1260.             new->code=DIV;
  1261.             new->q1=p->o;
  1262.             new->q2.flags=KONST;
  1263.             vlong=szof(p->left->ntyp->next);
  1264.             vint=zl2zi(vlong);
  1265.             new->q2.val.vint=vint;
  1266.             new->z=p->o;
  1267.             new->typf=INT;
  1268.             add_IC(new);
  1269.         }
  1270.         return(f);
  1271.     }
  1272.     if((p->flags==ADD||p->flags==SUB)&&(p->ntyp->flags&15)==POINTER){
  1273.     /*  Addieren und Subtrahieren eines Integers zu einem Pointer   */
  1274.         if(p->flags==ADD) new->code=ADDI2P; else new->code=SUBIFP;
  1275.         new->typf=p->right->ntyp->flags&31;
  1276.         new->q1=p->left->o;
  1277.         /*  kleinere Typen als MINADDI2P erst in diesen wandeln */
  1278.         if((new->typf&15)<MINADDI2P){convert(p->right,/*UNSIGNED|*/MINADDI2P);new->typf=/*UNSIGNED|*/MINADDI2P;}
  1279.         new->q2=p->right->o;
  1280.         if(!dest&&(p->left->o.flags&SCRATCH)&®ok(new->q1.reg,POINTER,p->left->ntyp->next->flags&31)){
  1281.             new->z=p->left->o;
  1282.             new->z.flags&=(~DREFOBJ);
  1283.         }else{
  1284.             get_scratch(&new->z,POINTER,p->left->ntyp->next->flags&31);
  1285.         }
  1286.         p->o=new->z;
  1287.         add_IC(new);
  1288.         return(f);
  1289.     }
  1290.     convert(p->left,p->ntyp->flags&31);
  1291.     convert(p->right,p->ntyp->flags&31);
  1292.     new->q1=p->left->o;
  1293.     new->q2=p->right->o;
  1294.     new->typf=p->ntyp->flags&31;
  1295.     /*  Bei dest!=0, d.h. ASSIGNADD, darf q1 nicht als Ziel benuzt werden!  */
  1296.     if(!dest&&(new->q1.flags&SCRATCH)&®ok(new->q1.reg,p->ntyp->flags,0)){
  1297.         new->z=new->q1;
  1298.         new->z.flags&=~DREFOBJ;
  1299.     }else{
  1300.         if((new->q2.flags&SCRATCH)&®ok(new->q2.reg,p->ntyp->flags,0)){
  1301.             if((p->flags>=OR&&p->flags<=AND)||p->flags==ADD||p->flags==MULT||p->flags==PMULT){
  1302.             /*  bei kommutativen Operatoren vertauschen     */
  1303.                 new->z=new->q2;
  1304.                 new->q2=new->q1;
  1305.                 new->q1=new->z;
  1306.                 new->z.flags&=~DREFOBJ;
  1307.             }else{
  1308.                 if(USEQ2ASZ){
  1309.                     new->z=new->q2;
  1310.                     new->z.flags&=~DREFOBJ;
  1311.                 }else{
  1312.                     get_scratch(&new->z,new->typf,0);
  1313.                 }
  1314.             }
  1315.         }else{
  1316.             get_scratch(&new->z,new->typf,0);
  1317.         }
  1318.     }
  1319.     p->o=new->z;
  1320.     add_IC(new);
  1321.     return(f);
  1322. }
  1323. void savescratch(int code,struct IC *p,int dontsave)
  1324. /*  speichert Scratchregister bzw. stellt sie wieder her (je nach code  */
  1325. /*  entweder MOVEFROMREG oder MOVETOREG)                                */
  1326. {
  1327.     int i,s,e,b;struct IC *new;
  1328.     if(code==MOVETOREG){ s=1;e=MAXR+1;b=1;} else {s=MAXR;e=0;b=-1;}
  1329.     for(i=s;i!=e;i+=b){
  1330.         if(regs[i]&&!(regs[i]&32)&®scratch[i]&&i!=dontsave){
  1331.             if(!regsbuf[i]){
  1332.                 struct Typ *t;
  1333.                 if(code!=MOVEFROMREG) continue;
  1334.                 t=mymalloc(TYPS);
  1335.                 t->flags=ARRAY;
  1336.                 t->size=regsize[i];
  1337.                 t->next=mymalloc(TYPS);
  1338.                 t->next->flags=CHAR;
  1339.                 t->next->next=0;
  1340.                 regsbuf[i]=add_var(empty,t,AUTO,0);
  1341.                 regbnesting[i]=nesting;
  1342.             }
  1343.             new=mymalloc(ICS);
  1344.             new->typf=new->q2.flags=0;
  1345.             new->line=0;new->file=0;
  1346.             new->code=code;
  1347.             if(code==MOVEFROMREG){
  1348.                 new->q1.flags=REG;new->q1.reg=i;
  1349.                 new->z.flags=VAR;new->z.v=regsbuf[i];
  1350.                 new->z.val.vlong=l2zl(0L);
  1351.             }else{
  1352.                 new->z.flags=REG;new->z.reg=i;
  1353.                 new->q1.flags=VAR;new->q1.v=regsbuf[i];
  1354.                 new->q1.val.vlong=l2zl(0L);
  1355.             }
  1356.             new->use_cnt=new->change_cnt=0;
  1357.             new->use_list=new->change_list=0;
  1358.             insert_IC(p,new);
  1359.         }
  1360.     }
  1361. }
  1362.  
  1363.